package com.qire.manhua.view.comicReader.renderer.download;

import android.util.Log;

import com.qire.common.basic.StringUtil;
import com.qire.manhua.view.comicReader.renderer.IDownloader;
import com.qire.manhua.view.comicReader.renderer.IPictureLoader;
import com.qire.manhua.view.comicReader.renderer.IPictureLoader.LoaderState;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

/**
 * @title 根据 图片url地址下载图片 可以是本地和网络
 */
public class ComicPictureDownloader implements IDownloader {

	private static final String TAG = ComicPictureDownloader.class.getSimpleName();
	private static final int IO_BUFFER_SIZE = 8 * 1024; // 8k

	public ComicPictureDownloader() { }

	@Override
	public byte[] download (String urlString, IPictureLoader pictureLoader) {
		if (urlString == null) {
			return null;
		}

		String schemeType = urlString.trim().toLowerCase();

		if (schemeType.startsWith("http")) {
			// http: 或 https:
			return getFromHttp(urlString, pictureLoader);
		} else if(schemeType.startsWith("file:")) {
			// file:
			try {
				File file = new File(new URI(urlString));
				if (file.exists() && file.canRead()) {
					return getFromFile(file, pictureLoader);
				}
			} catch (URISyntaxException e) {
				Log.e(TAG, "Error in read from file - " + urlString + " : " + e);
			}
		} else {
			// uri 或其他
			File file = new File(urlString);
			if (file.exists() && file.canRead()) {
				return getFromFile(file, pictureLoader);
			}
		}
		
		return null;
	}

	private byte[] getFromFile(File file, IPictureLoader pictureLoader) {
		if(file == null) return null;

		long totalSize = file.length();

		FileInputStream fis = null;
		try {
			fis = new FileInputStream(file);
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			int len = 0;
			byte[] buffer = new byte[1024];
			while ((len = fis.read(buffer)) != -1) {
				baos.write(buffer, 0, len);
				pictureLoader.updateProgress(len, totalSize);
			}
			return baos.toByteArray();
		} catch (Exception e) {
			Log.e(TAG, "Error in read from file - " + file + " : " + e);
		} finally {
			pictureLoader.onStateChange(LoaderState.FINISH);
			if (fis != null) {
				try {
					fis.close();
					fis = null;
				} catch (IOException e) {
					// do nothing
				}
			}
		}

		return null;
	}

	private byte[] getFromHttp(String urlString, IPictureLoader pictureLoader) {
		FlushedInputStream		in				= null;			//缓冲输入流，从服务器获取
		HttpURLConnection urlConnection	= null;			//http连接对象

		int len;																							//每次读取的数组长度
		byte[] buffer = new byte[1024 * 8];																	//流读写的缓冲区

		try {
			final URL url = new URL(urlString);
			urlConnection = (HttpURLConnection) url.openConnection();

//			urlConnection.setConnectTimeout(120000);														//连接超时时间
//			urlConnection.setReadTimeout(120000);															//读取超时时间
//			urlConnection.setRequestMethod("GET");															//请求类型为GET
			urlConnection.addRequestProperty("Connection", "Keep-Alive");									//设置为长连接模式

			urlConnection.connect();																		//连接
			String contentLength = urlConnection.getHeaderField("content-length");
			long totalSize = StringUtil.valueToLong(contentLength, 0);									//获取文件长度
//			int stepSize,

			InputStream connectionInputStream = urlConnection.getInputStream();
			in = new FlushedInputStream(new BufferedInputStream(connectionInputStream, IO_BUFFER_SIZE));	//获取输入流并且包装为缓冲流
			ByteArrayOutputStream baos = new ByteArrayOutputStream();										//字节输出流，保存从服务器获取的数据
			while ((len = in.read(buffer)) != -1) {															//从流读取字节数组到缓冲区
				baos.write(buffer, 0, len);																//把字节数组写入到字节缓存
				pictureLoader.updateProgress(len, totalSize);												//更新任务信息中的完成的文件长度属性
			}
			//开启长连接为了复用连接，关闭流即可，如果调用urlConnection.disconnect();则可能会关闭连接
			connectionInputStream.close();
			return baos.toByteArray();
		} catch (final IOException e) {
			pictureLoader.onStateChange(LoaderState.ERROR);
			Log.e(TAG, "Error in downloadBitmap - " + urlString + " : " + e);
			//如果开启长连接复用，使用下面代码可以处理错误是数据流处理，目前不使用。若有需求则可使用
//			try {
//				int respCode = urlConnection.getResponseCode();
//				InputStream es = urlConnection.getErrorStream();
//				int ret = 0;
//				// read the response body
//				while ((ret = es.read(buf)) > 0) {
//					processBuf(buf);
//				}
//				// close the errorstream
//				es.close();
//			} catch(IOException ex) {
//				// deal with the exception
//			}

		} finally {
			pictureLoader.onStateChange(LoaderState.FINISH);
			// 开启长连接为了复用连接，关闭流即可，如果调用urlConnection.disconnect();则可能会关闭连接，
			// 理论上如果留关闭调用该方法会关闭连接，如果没有关闭则检查是否开启长连接模式而决定关闭不关闭
//			if (urlConnection != null) {
//				urlConnection.disconnect();
//			}
			try {
				if (in != null) {
					in.close();
				}
			} catch (final IOException e) {}
		}
		return null;
	}

	public class FlushedInputStream extends FilterInputStream {
		public FlushedInputStream(InputStream inputStream) {
			super(inputStream);
		}

		@Override
		public long skip(long n) throws IOException {
			long totalBytesSkipped = 0L;
			while (totalBytesSkipped < n) {
				long bytesSkipped = in.skip(n - totalBytesSkipped);
				if (bytesSkipped == 0L) {
					int by_te = read();
					if (by_te < 0) {
						break; // we reached EOF
					} else {
						bytesSkipped = 1; // we read one byte
					}
				}
				totalBytesSkipped += bytesSkipped;
			}
			return totalBytesSkipped;
		}
	}

}